package com.xian.cloud.receiver;

import com.xian.cloud.facead.Demo;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;

/**
 * @Author: xlr
 * @Date: Created in 下午1:03 2018/10/27
 */
@Configuration
public class RabbitConfig implements ApplicationContextAware,BeanDefinitionRegistryPostProcessor {

    private static ApplicationContext applicationContext;

    private static BeanDefinitionRegistry beanDefinitionRegistry;

    private static ConfigurableListableBeanFactory configurableListableBeanFactory;


    @Autowired
    RabbitProperties rabbitProperties;

    @Autowired
    private Environment env;

    @Bean
    @Qualifier("connectionFactory")
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(rabbitProperties.getHost(),rabbitProperties.getPort());
        connectionFactory.setUsername(rabbitProperties.getUsername());
        connectionFactory.setPassword(rabbitProperties.getPassword());
        connectionFactory.setVirtualHost(rabbitProperties.getVirtualHost());
        connectionFactory.setPublisherConfirms(rabbitProperties.isPublisherConfirms());
        return connectionFactory;
    }

    @Bean(value = "pmsRabbitAdmin")
    public RabbitAdmin pmsRabbitAdmin(@Qualifier("connectionFactory")ConnectionFactory connectionFactory ){
        RabbitAdmin rabbitAdmin=new RabbitAdmin(connectionFactory);
        return rabbitAdmin;
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    //必须是prototype类型
    @Qualifier("rabbitTemplate")
    public RabbitTemplate rabbitTemplate(@Qualifier("connectionFactory")ConnectionFactory connectionFactory ) {
        RabbitTemplate template = new RabbitTemplate( connectionFactory );
        return template;
    }

    @Bean
    public SimpleMessageListenerContainer listenerContainer(@Qualifier("connectionFactory")ConnectionFactory connectionFactory) throws Exception {
        String queueName = env.getProperty("mq.queue").trim();
        SimpleMessageListenerContainer simpleMessageListenerContainer = new SimpleMessageListenerContainer(connectionFactory);
        simpleMessageListenerContainer.setQueueNames(queueName);
        //simpleMessageListenerContainer.setMessageListener(mailMessageListenerAdapter);
        simpleMessageListenerContainer.setConcurrentConsumers( 1 );
        // 设置手动 ACK
        simpleMessageListenerContainer.setAcknowledgeMode( AcknowledgeMode.MANUAL);

        return simpleMessageListenerContainer;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        RabbitConfig.applicationContext = applicationContext;
    }

    ApplicationContext getApplicationContext(){
        return RabbitConfig.applicationContext;
    }

    public static void registerBean(String beanId,String className) {
        // get the BeanDefinitionBuilder
        BeanDefinitionBuilder beanDefinitionBuilder = getBeanDefinitionBuilder( className);
        registerBeanDefinition(beanDefinitionBuilder,beanId);
    }
    public static void registerBean(String beanId,Class className) {
        // get the BeanDefinitionBuilder
        BeanDefinitionBuilder beanDefinitionBuilder = getBeanDefinitionBuilder( className);
        registerBeanDefinition(beanDefinitionBuilder,beanId);
    }

    public static void registerBeanDefinition(BeanDefinitionBuilder beanDefinitionBuilder,String beanId ){
        // get the BeanDefinition
        BeanDefinition beanDefinition=beanDefinitionBuilder.getBeanDefinition();
        // register the bean
        beanDefinitionRegistry.registerBeanDefinition(beanId,beanDefinition);
    }

    public static BeanDefinitionBuilder getBeanDefinitionBuilder(String className){
        return BeanDefinitionBuilder.genericBeanDefinition( className);
    }

    public static BeanDefinitionBuilder getBeanDefinitionBuilder(Class clazz){
        return BeanDefinitionBuilder.genericBeanDefinition( clazz);
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        RabbitConfig.beanDefinitionRegistry = beanDefinitionRegistry;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        RabbitConfig.configurableListableBeanFactory = configurableListableBeanFactory;
    }
}